#include <iostream>
#include <cstdlib>
#include <string>
#include <tuple>
#include <regex>
#include <unordered_map>
#include <atomic>
#include <thread>

#include "cmdline.h"
#include "http.hpp"
#include "utils.hpp"
#include "socket.hpp"

HTTPRequest build_request(std::string &url)
{
    std::string protocol, host, path;
    std::tie(protocol, host, path) = url_split(url);
    HTTPRequest req;
    req.set_method(HTTPRequestLine::Method::GET);
    req.append_header(HTTPHeader::Keys::USER_AGENT, "Webench++ 0.0.1");
    req.append_header(HTTPHeader::Keys::HOST, host);
    req.append_header(HTTPHeader::Keys::CONNECTION, "close");
    std::cout << req << std::endl;
    return req;
}

int main(int argc, char *argv[])
{
    cmdline::parser option_parser;
    option_parser.add<std::string>("host", 'h', "target host, URL or ip address", false, "http://www.baidu.com/");
    option_parser.add<unsigned int>("nthread", 't', "number of threads", false, 1);
    option_parser.parse_check(argc, argv);
    std::string target_url = option_parser.get<std::string>("host");
    unsigned int nthread = option_parser.get<unsigned int>("nthread");

    Counter counter;

    HTTPRequest req = build_request(target_url);
    const std::string host = std::get<1>(url_split(target_url));

    auto test = [&req, &host, &counter]() {
        TCPSocket ts(host, 80);
        if (ts.connect() == 0)
        {
            if (ts.write(req.to_string()))
            {
                ts.read(-1);
                counter.success();
            }
            else
            {
                counter.failed();
            }
        }
        else
        {
            counter.failed();
        }
    };
    std::vector<std::thread> ts;
    ts.reserve(nthread);
    for (int i = 0; i < nthread; ++i)
    {
        std::thread t(test);
        ts.emplace_back(std::move(t));
    }
    for (auto &t : ts)
    {
        t.join();
    }
    int total, succ, failed;
    std::tie(total, succ, failed) = counter.summary();
    printf("SUMMERY:\n");
    printf("\tTotal %d\tSuccess: %d\tFailed: %d\n", total, succ, failed);
    return 0;
}